package com.kakarote.admin.controller;


import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.util.NumberUtil;
import com.kakarote.admin.entity.BO.AdminDeleteByBatchIdBO;
import com.kakarote.admin.entity.BO.AttachmentBO;
import com.kakarote.admin.entity.BO.RenameFileBO;
import com.kakarote.admin.entity.PO.AdminFile;
import com.kakarote.admin.service.IAdminFileService;
import com.kakarote.common.log.annotation.OperateLog;
import com.kakarote.common.log.entity.OperationLog;
import com.kakarote.common.log.entity.OperationResult;
import com.kakarote.common.log.enums.ApplyEnum;
import com.kakarote.common.log.enums.BehaviorEnum;
import com.kakarote.common.log.enums.OperateObjectEnum;
import com.kakarote.common.upload.service.FileService;
import com.kakarote.core.common.ApiExplain;
import com.kakarote.core.common.Result;
import com.kakarote.core.common.enums.SystemCodeEnum;
import com.kakarote.core.entity.UploadEntity;
import com.kakarote.core.exception.CrmException;
import com.kakarote.core.feign.admin.entity.FileEntity;
import com.kakarote.core.servlet.LoginFromCookie;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.*;

/**
 * <p>
 * 附件表 前端控制器
 * </p>
 *
 * @author zhangzhiwei
 * @since 2020-04-27
 */
@RestController
@RequestMapping("/adminFile")
@Api(tags = "文件操作相关接口")
public class AdminFileController {

    @Autowired
    private IAdminFileService adminFileService;

    @Autowired
    private FileService fileService;

    @PostMapping("/upload")
    @ApiOperation("上传文件")
    public Result<UploadEntity> upload(@RequestParam("file")
                                       @ApiParam("文件") MultipartFile file,
                                       @ApiParam("batchId") String batchId,
                                       @ApiParam("文件类型") String type,
                                       @RequestParam(value = "isPublic", required = false) Integer isPublic) {
        if (isPublic == null) {
            isPublic = 0;
        }
        String fileType;
        try {
            fileType = FileTypeUtil.getType(file.getInputStream(), file.getOriginalFilename());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        UploadEntity entity = adminFileService.upload(file, batchId, type, isPublic);
        entity.setType(fileType);
        return Result.ok(entity);
    }

    @PostMapping("/uploadTempFile")
    @ApiOperation("上传文件")
    public Result<UploadEntity> upload(@RequestParam("file")
                                       @ApiParam("文件") MultipartFile file,
                                       @ApiParam("batchId") String batchId) {
        UploadEntity entity = adminFileService.uploadTempFile(file, batchId);
        return Result.ok(entity);
    }

    @PostMapping("/uploadBySingle")
    @ApiOperation("上传文件")
    public Result<UploadEntity> uploadBySingle(@RequestParam("file")
                                               @ApiParam("文件") MultipartFile file,
                                               @ApiParam("batchId") String batchId,
                                               @ApiParam("文件类型") String type,
                                               @RequestParam(value = "isPublic", required = false) Integer isPublic) {
        UploadEntity entity = adminFileService.uploadBySingle(file, batchId, type, isPublic);
        return Result.ok(entity);
    }

    @RequestMapping(value = "/queryFileList/{batchId}", method = RequestMethod.POST)
    @ApiOperation(value = "通过批次ID查询文件列表", httpMethod = "POST")
    public Result<List<FileEntity>> queryFileList(@NotNull @PathVariable("batchId") String batchId) {
        List<FileEntity> entityList = adminFileService.queryFileList(batchId);
        return Result.ok(entityList);
    }

    @RequestMapping(value = "/queryById/{fileId}", method = RequestMethod.POST)
    @ApiOperation(value = "通过ID查询文件", httpMethod = "POST")
    public Result<FileEntity> queryById(@NotNull @PathVariable("fileId") @ApiParam("文件ID") Long fileId) {
        FileEntity fileEntity = adminFileService.queryById(fileId);
        return Result.ok(fileEntity);
    }

    @RequestMapping(value = "/queryByIds", method = RequestMethod.POST)
    @ApiOperation(value = "通过ID查询文件", httpMethod = "POST")
    public Result<List<FileEntity>> queryByIds(@RequestBody Collection<Long> fileIds) {
        List<FileEntity> fileEntitys = adminFileService.queryByIds(fileIds);
        return Result.ok(fileEntitys);
    }

    @RequestMapping(value = "/queryOneByBatchId/{batchId}", method = RequestMethod.POST)
    @ApiOperation(value = "通过批次ID查询单个文件", httpMethod = "POST")
    public Result<FileEntity> queryOneByBatchId(@NotNull @PathVariable("batchId") @ApiParam("batchId") String batchId) {
        FileEntity fileEntity = adminFileService.queryOneByBatchId(batchId);
        return Result.ok(fileEntity);
    }

    @RequestMapping(value = "/deleteById/{fileId}", method = RequestMethod.POST)
    @ApiOperation(value = "通过ID删除文件", httpMethod = "POST")
    public Result deleteById(@NotNull @PathVariable("fileId") @ApiParam("文件ID") String fileId) {
        if (NumberUtil.isLong(fileId)) {
            adminFileService.deleteById(Long.parseLong(fileId));
        } else {
            AdminDeleteByBatchIdBO bo = new AdminDeleteByBatchIdBO();
            bo.setBatchId(fileId);
            adminFileService.deleteByBatchId(bo);
        }
        return Result.ok();
    }

    @RequestMapping(value = "/deleteByBatchId", method = RequestMethod.POST)
    @ApiOperation(value = "通过批次ID和文件类型删除文件", httpMethod = "POST")
    public Result deleteByBatchId(@RequestBody AdminDeleteByBatchIdBO deleteByBatchIdBO) {
        adminFileService.deleteByBatchId(deleteByBatchIdBO);
        return Result.ok();
    }

    @RequestMapping(value = "/deleteByBatchIds", method = RequestMethod.POST)
    @ApiOperation(value = "通过批次ID删除文件", httpMethod = "POST")
    public Result deleteByBatchId(@RequestBody @ApiParam("batchId") List<String> batchId) {
        adminFileService.deleteByBatchId(batchId);
        return Result.ok();
    }

    @RequestMapping(value = "/down/{fileId}", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation(value = "下载文件接口", httpMethod = "POST")
    public void down(@PathVariable("fileId") @ApiParam("文件ID") Long fileId, HttpServletResponse response) {

        adminFileService.down(response, fileId);
    }

    @PostMapping(value = "/getFileStreamByPath")
    @ApiOperation(value = "获取文件流", httpMethod = "POST")
    public void getFileStreamByPath(@RequestBody com.kakarote.common.upload.entity.UploadEntity upload, HttpServletResponse response) {
        adminFileService.getFileStreamByPath(upload, response);
    }

    @RequestMapping(value = "/getFileBaseById/{fileId}")
    @ApiOperation(value = "获取文件流", httpMethod = "POST")
    public Result<String> getFileBaseById(@PathVariable("fileId") @ApiParam("文件ID") Long fileId, HttpServletResponse response) throws IOException {
        String base64 = adminFileService.getFileBaseById(fileId, response);
        return Result.ok(base64);
    }

    @PostMapping(value = "/renameFileById")
    @ApiOperation(value = "修改附件名称", httpMethod = "POST")
    public Result renameFileById(@RequestBody RenameFileBO renameFileBO) {
        adminFileService.renameFileById(renameFileBO);
        return Result.ok();
    }

    @PostMapping(value = "/queryNum")
    @ApiExplain("查询文件数量")
    public Result<Integer> queryNum(@RequestBody List<String> batchId) {
        Integer num = adminFileService.queryNum(batchId);
        return Result.ok(num);
    }

    @PostMapping(value = "/queryFileList")
    @ApiExplain("查询文件")
    public Result<List<FileEntity>> queryFileList(@RequestBody List<String> batchIdList) {
        List<FileEntity> fileEntities = adminFileService.queryFileList(batchIdList);
        return Result.ok(fileEntities);
    }


    @PostMapping(value = "/copyFile")
    @ApiExplain("复制文件")
    public Result<String> copyFile(@RequestParam(value = "batchId", required = false) String batchId) {
        String newBatchId = adminFileService.copyFile(batchId);
        return Result.ok(newBatchId);
    }


    @PostMapping(value = "/updateFileBatchId")
    @ApiExplain("修改文件BatchId")
    public Result updateFileBatchId(@RequestParam(value = "oldBatchId") String oldBatchId,
                                    @RequestParam(value = "newBatchId") String newBatchId) {
        adminFileService.updateFileBatchId(oldBatchId, newBatchId);
        return Result.ok();
    }


    @PostMapping("/attachments/upload")
    @ApiOperation("上传文件")
    @OperateLog(behavior = BehaviorEnum.UPLOAD)
    public Result<UploadEntity> attachmentsUpload(AttachmentBO attachmentBO) {
        boolean checked = attachmentBO.checkData();
        if (!checked) {
            throw new CrmException(SystemCodeEnum.SYSTEM_NO_VALID);
        }

        UploadEntity entity = adminFileService.upload(attachmentBO.getFile(), attachmentBO.getBatchId(), attachmentBO.getType(), 0);
        return OperationResult.ok(entity, ListUtil.toList(addOperationLog(attachmentBO, entity.getFileId(), "上传文件：" + entity.getName())));
    }

    @RequestMapping(value = "/attachments/down", method = {RequestMethod.POST, RequestMethod.GET})
    @ApiOperation(value = "下载文件接口", httpMethod = "POST")
    @LoginFromCookie
    @OperateLog(behavior = BehaviorEnum.DOWNLOAD)
    public Result<OperationLog> attachmentsDown(AttachmentBO attachmentBO, HttpServletResponse response) {
        boolean checked = attachmentBO.checkData();
        if (!checked) {
            throw new CrmException(SystemCodeEnum.SYSTEM_NO_VALID);
        }
        OperateObjectEnum operateObjectEnum = OperateObjectEnum.parse(attachmentBO.getLabel(), attachmentBO.getApply());
        if (operateObjectEnum == OperateObjectEnum.NULL) {
            throw new CrmException(SystemCodeEnum.SYSTEM_NO_VALID);
        }
        AdminFile down = adminFileService.down(response, attachmentBO.getFileId());
        return OperationResult.ok(addOperationLog(attachmentBO, down.getFileId(), "下载文件：" + down.getName()));

    }

    @PostMapping(value = "/attachments/del")
    @ApiOperation(value = "通过ID删除文件", httpMethod = "POST")
    @OperateLog(behavior = BehaviorEnum.DELETE)
    public Result attachmentsDeleteById(AttachmentBO attachmentBO) {
        boolean checked = attachmentBO.checkData();
        if (!checked) {
            throw new CrmException(SystemCodeEnum.SYSTEM_NO_VALID);
        }
        AdminFile adminFile = adminFileService.deleteById(attachmentBO.getFileId());
        return OperationResult.ok(addOperationLog(attachmentBO, adminFile.getFileId(), "删除文件：" + adminFile.getName()));
    }

    /**
     * 添加操作日志
     */
    private OperationLog addOperationLog(AttachmentBO attachmentBO, Object fileId, String operationInfo){
        OperationLog operationLog = new OperationLog();
        operationLog.setOperationObject(attachmentBO.getTypeId(), attachmentBO.getTypeName());
        operationLog.setOperationObject("fileId", fileId);
        operationLog.setOperationInfo(operationInfo);
        operationLog.setApply(ApplyEnum.parse(attachmentBO.getApply()));
        operationLog.setApplyObject(OperateObjectEnum.parse(attachmentBO.getLabel(), attachmentBO.getApply()));
        return operationLog;
    }


    @GetMapping(value = "/queryFilePath")
    @ApiExplain("获取文件上传路径")
    public Result<Map<Integer,String>> queryFilePath() {
        Map<Integer,String> map = new HashMap<>();
        map.put(com.kakarote.core.entity.UploadEntity.PUBLIC_KEY, fileService.getProperties().getExtra().get("publicBucket").toString());
        map.put(com.kakarote.core.entity.UploadEntity.PRIVATE_KEY, fileService.getProperties().getBucketName());
        return Result.ok(map);
    }


}

